package com.qq.service;

import com.qq.common.Message;
import com.qq.common.MessageType;
import com.qq.common.User;

import java.io.*;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Paths;

public class QQClientService {
    private final User user  = new User();

    /**
     * 功能：判断登陆状态，若登录成功，将会启动一个线程维持与服务器的通信，同时会将线程添加到HashMap中
     * @param userId 登录id
     * @param passwd 登录密码
     * @return 登陆成功返回true 失败返回false
     */
    public boolean login(String userId, String passwd) {
        user.setUserId(userId);
        user.setPasswd(passwd);
        Socket socket;
        ObjectOutputStream objectOutputStream;
        ObjectInputStream objectInputStream;
        boolean confirm = false;
        try {
            //连接到服务器
            socket = new Socket("192.168.1.192", 8888);
            //向服务器发送user对象，其中包含id和密码
            objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            objectOutputStream.writeObject(user);
            objectOutputStream.flush();
            //接收服务器返回信息
            objectInputStream = new ObjectInputStream(socket.getInputStream());
            try {
                //将返回的消息转换类型并判断是否登录成功
                Message loginConfirmation = (Message) objectInputStream.readObject();
                //通过返回消息中的MesType来判断是否登录成功
                if (loginConfirmation.getMesType().equals(MessageType.MESSAGE_LOGIN_SUCCEED)) {
                    //登录成功后创建线程并添加到集合中
                    ClientConnectServerThread clientConnectServerThread = new ClientConnectServerThread(socket);
                    //将线程设置为守护线程，在主线程结束后，该通信线程也会结束
                    clientConnectServerThread.setDaemon(true);
                    clientConnectServerThread.start();
                    //添加到线程集合中
                    ManageClientThread.addClient(userId, clientConnectServerThread);
                    confirm = true;
                } else {
                    socket.close();
                }
            } catch (ClassNotFoundException e) {
                System.out.println("接收服务器登录验证结果时出现错误！" + e.getMessage());
            }
        } catch (IOException e) {
            System.out.println("连接服务器时出现错误！" + e.getMessage());
        }
        return confirm;
    }

    /**
     * 功能：该方法会向服务器发送获取在线用户列表的请求
     */
    public void onlineUsersList() {
        //获取一个message对象并将其消息类型设置为获取在线用户列表状态
        Message message = new Message();
        message.setMesType(MessageType.MESSAGE_GET_ONLINE_USERS);
        //从线程集合中获取当前登录账户所对应的线程
        ClientConnectServerThread client = ManageClientThread.getClient(user.getUserId());
        try {
            //通过该线程获取其socket，得到对象输出流，并发送message对象
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(client.getSocket().getOutputStream());
            objectOutputStream.writeObject(message);
            objectOutputStream.flush();
        } catch (IOException e) {
            System.out.println("发送请求时出现错误！" + e.getMessage());
        }
    }

    /**
     * 功能：该方法会向服务器发送下线请求
     */
    public void logOut() {
        Message logOutMes = new Message();
        logOutMes.setMesType(MessageType.MESSAGE_CLIENT_EXIT);
        ClientConnectServerThread client = ManageClientThread.getClient(user.getUserId());
        try {
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(client.getSocket().getOutputStream());
            objectOutputStream.writeObject(logOutMes);
            objectOutputStream.flush();
            System.out.println("已经向服务器发送下线请求！");
        } catch (IOException e) {
            System.out.println("退出登录请求发送失败！" + e.getMessage());
        }
    }

    /**
     * 功能：向指定用户发送私聊信息
     * @param getterId 接收者id
     * @param content 发送内容
     */
    public void sendMessage(String getterId, String content) {
        Message message = new Message();
        message.setGetter(getterId);
        message.setContent(content);
        message.setMesType(MessageType.MESSAGE_COMM_MES);
        ClientConnectServerThread client = ManageClientThread.getClient(user.getUserId());
        try {
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(client.getSocket().getOutputStream());
            objectOutputStream.writeObject(message);
            objectOutputStream.flush();
        } catch (IOException e) {
            System.out.println("发送失败！" + e.getMessage());
        }
    }

    /**
     * 功能：向所有在线成员发送消息
     * @param content 发送内容
     */
    public void sendMessageToAll(String content) {
        Message message = new Message();
        message.setMesType(MessageType.MESSAGE_MASS_MES);
        message.setContent(content);
        message.setSender(user.getUserId());
        ClientConnectServerThread client = ManageClientThread.getClient(user.getUserId());
        try {
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(client.getSocket().getOutputStream());
            objectOutputStream.writeObject(message);
            objectOutputStream.flush();
        } catch (IOException e) {
            System.out.println("群发消息发送失败！" + e.getMessage());
        }
    }

    /**
     * 功能：向指定用户发送文件
     * @param fileGetter 文件接收者
     * @param path 文件路径
     * @param fileType 文件类型
     */
    public void sendFile(String fileGetter, String path, String fileType) {
        //获取一个新的message对象
        Message message = new Message();
        //判断发送文件类型，并将其设置为相应的状态属性
        if (fileType.equals("文本文件")) {
            message.setMesType(MessageType.MESSAGE_SEND_TEXT_FILE_MES);
        }
        if (fileType.equals("二进制文件")) {
            message.setMesType(MessageType.MESSAGE_SEND_BINARY_FILE_MES);
        }
        message.setSender(user.getUserId());
        //设置接收者id
        message.setGetter(fileGetter);
        String[] split = path.split("\\\\");
        message.setContent(split[split.length - 1]);

        ClientConnectServerThread client = ManageClientThread.getClient(user.getUserId());
        try {
            //将文件全部读取到字节数组
            byte[] bytes = Files.readAllBytes(Paths.get(path));
            //将字节数组赋给一个object对象并发送
            message.setData(bytes);
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(client.getSocket().getOutputStream());
            objectOutputStream.writeObject(message);
            objectOutputStream.flush();
        } catch (FileNotFoundException e) {
            System.out.println("文件读取出现异常！" + e.getMessage());
        } catch (IOException e) {
            System.out.println("将文件读取到字符数组时出现错误！" + e.getMessage());
        }
    }
}
